import requests
from bs4 import BeautifulSoup
import pandas as pd
from datetime import datetime, timedelta
import asyncio

# 请求的URL
url = "https://yield.chinabond.com.cn/gkh/yield"
# 爬虫存入文件地址
file_path = '../data/2024_tenY_cdb.xlsx'

# 转成dataframe 数据格式
data = {
  '日期': [],
  '10年': []
}
old_data = pd.DataFrame(data)
# 尝试读取 Excel 文件
try:
  # 如果文件存在，读取 Excel 文件
  old_data = pd.read_excel(file_path)
except FileNotFoundError:
  print(f"文件 {file_path} 不存在，使用默认数据创建 DataFrame")


def save_table():
  new_data = pd.DataFrame(data)
  # table_data = pd.merge(old_data, new_data, on=['日期', '10年'], how='outer')
  table_data = pd.concat([old_data, new_data], axis=0)
  # 对 '日期' 列进行升序排序
  table_data = table_data.sort_values(by='日期', ascending=True)
  table_data = table_data.drop_duplicates(subset='日期', keep='first')
  print(table_data)

  # 使用to_excel方法将DataFrame保存为Excel文件
  try:
    table_data.to_excel(file_path, index=False)  # 设置index=False表示不保存行索引
    print(f"数据已成功保存至 {file_path}")
  except Exception as e:
    print(f"保存数据时出现错误: {e}")


async def set_sign_data(date):
  # 请求参数
  params = {
    "searchDate": date
  }
  try:
    # 发送POST请求
    # print(date)
    # print('post start')
    response = requests.post(url, data=params)
    response.raise_for_status()  # 如果请求出现错误，抛出异常

    # 使用BeautifulSoup解析HTML
    soup = BeautifulSoup(response.text, 'html.parser')
    # 根据选择器获取元素并提取文本内容
    element = soup.select('#conter tr:nth-child(6) td:nth-child(2)')
    if element:
      value = element[0].get_text(strip=True)
      data['10年'].append(value)
      data['日期'].append(date)
      print('post end', date, value)
    else:
      print('post end no value', date)
  except requests.RequestException as e:
    print(f"请求出现错误: {e}")


async def set_data_by(start_date_str, end_date_str):
  # 将输入的日期字符串转换为日期对象
  start_date = datetime.strptime(start_date_str, '%Y%m%d')
  end_date = datetime.strptime(end_date_str, '%Y%m%d')

  # 判断开始日期是否大于等于结束日期，如果是则报错
  if start_date > end_date:
    raise ValueError("开始日期必须小于结束日期")

  # 循环打印日期
  current_date = start_date
  while current_date <= end_date:
    current_date_str = current_date.strftime('%Y-%m-%d')
    if current_date_str not in old_data['日期']:
      print(current_date_str)
      await asyncio.sleep(0.5)  # 避免过快发送请求
      await set_sign_data(current_date_str)
    current_date += timedelta(days=1)
  save_table()

# 获取当前日期

# 计算6个月前的日期（可按需调整时间范围，这里以10天为例）


def set_during10_before(days):
  default_days = 365 * 2
  end_date = datetime.now()
  end_date = end_date - timedelta(days=days)
  start_date = end_date - timedelta(days=default_days)
  end_date_str = end_date.strftime('%Y%m%d')  # 格式 20240101
  start_date_str = start_date.strftime('%Y%m%d')
  return [start_date_str, end_date_str]


def main():
  start_date_str, end_date_str = set_during10_before(0)
  print(start_date_str, end_date_str)

  # 如果环境中已运行事件循环
  try:
    loop = asyncio.get_running_loop()
  except RuntimeError:
    loop = None

  if loop and loop.is_running():
    # 如果事件循环正在运行
    task = set_data_by(start_date_str, end_date_str)
    asyncio.ensure_future(task)  # 创建任务并调度运行
  else:
    # 如果没有事件循环，则使用 asyncio.run()
    asyncio.run(set_data_by(start_date_str, end_date_str))


main()
